<html>
<head><meta charset="utf-8"><title>RFC: Visibility · project-safe-transmute · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/index.html">project-safe-transmute</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html">RFC: Visibility</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="205405174"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205405174" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205405174">(Jul 29 2020 at 19:52)</a>:</h4>
<p>Hi, all. The RFC uses field visibility as an indicator of whether a field has library-imposed validity invariants on its value. This requirement is recursive: the fields of a field must <em>also</em> be <code>pub</code>, and so on. If a public type consists, recursively, of public fields with public types, a value of that type can be constructed naturally using Rust's initialization syntax. When this is the case, a type cannot meaningfully impose any restrictions on its fields' values using its constructors or methods.</p>



<a name="205405260"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205405260" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205405260">(Jul 29 2020 at 19:53)</a>:</h4>
<p>Unfortunately, it's possible to evade this using the public-in-private trick; e.g.:</p>
<div class="codehilite"><pre><span></span><code><span class="cp">#[derive(PromiseTransmutableInto, PromiseTransmutableFrom)]</span><span class="w"></span>
<span class="cp">#[repr(C)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">Constrained</span><span class="p">(</span><span class="k">pub</span><span class="w"> </span><span class="n">private</span>::<span class="n">ConstrainedInner</span><span class="p">);</span><span class="w"></span>

<span class="k">impl</span><span class="w"> </span><span class="n">Constrained</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="sd">/// the sum of `wizz` and `bang` must be greater than or equal to zero.</span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new</span><span class="p">(</span><span class="n">wizz</span>: <span class="kt">i8</span><span class="p">,</span><span class="w"> </span><span class="n">bang</span>: <span class="kt">u8</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">assert</span><span class="o">!</span><span class="p">((</span><span class="n">wizz</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">i16</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">bang</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">i16</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">Constrained</span><span class="p">(</span><span class="n">private</span>::<span class="n">ConstrainedInner</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">wizz</span><span class="p">,</span><span class="w"> </span><span class="n">bang</span><span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">something_dangerous</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// do something that&#39;s only safe if `self.0.wizz + self.0.bang &gt;= 0`</span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="c1">// introduce a private module to avoid `private_in_public` error (E0446):</span>
<span class="k">pub</span><span class="p">(</span><span class="k">crate</span><span class="p">)</span><span class="w"> </span><span class="k">mod</span> <span class="nn">private</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="sd">/// the sum of `wizz` and `bang` MUST be greater than or equal to zero.</span>
<span class="w">    </span><span class="sd">/// this invariant is maintained by convention within this crate.</span>
<span class="w">    </span><span class="cp">#[derive(PromiseTransmutableInto, PromiseTransmutableFrom)]</span><span class="w"></span>
<span class="w">    </span><span class="cp">#[repr(C)]</span><span class="w"></span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">ConstrainedInner</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">pub</span><span class="w"> </span><span class="n">wizz</span>: <span class="kt">i8</span><span class="p">,</span><span class="w"></span>
<span class="w">        </span><span class="k">pub</span><span class="w"> </span><span class="n">bang</span>: <span class="kt">u8</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>


<p>Given these definitions, the compiler will accept <code>u16: TransmuteInto&lt;Constrained&gt;</code>, even though using the resulting <code>Constrained</code> value may lead to unsafety if the <code>something_dangerous</code> method is called.</p>



<a name="205405549"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205405549" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205405549">(Jul 29 2020 at 19:55)</a>:</h4>
<p>Now, the above example requires the type author to do something a little odd: they derived <code>PromiseTransmutableFrom</code> for <code>Constrained</code>, thereby declaring that <code>Constrained</code> is stably instantiatiable via transmutation. If they didn't do this, the compiler would not accept <code>u16: TransmuteInto&lt;Constrained&gt;</code>.</p>



<a name="205405716"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205405716" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205405716">(Jul 29 2020 at 19:57)</a>:</h4>
<p>...but the compiler <em>would</em> still accept <code>u16: TransmuteInto&lt;Constrained, NeglectStability&gt;</code>. The <code>NeglectStability</code> option is currently the only option usable with safe transmutations. So, using this option, an end-user can <em>safely</em> construct an instance of <code>Constrained</code> for which calling <code>something_dangerous</code> would lead to memory unsafety.</p>



<a name="205406545"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205406545" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205406545">(Jul 29 2020 at 20:02)</a>:</h4>
<p><code>NeglectStability</code> exists so that end-users using types with documentation-only layout stability properties  (as opposed to implementations of this RFC's proposed stability declaration traits) can take advantage of this RFC's safety-checking mechanisms <em>without</em> resorting to unsafe transmutation.</p>



<a name="205407311"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205407311" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205407311">(Jul 29 2020 at 20:09)</a>:</h4>
<p>The maximally-safe thing for me to do  in light of this safety hole would be to demote <code>NeglectStability</code> to use with only <em>unsafe</em> transmutations. Unfortunately, doing so negates a lot of the current niceness of <code>NeglectStability</code>.</p>
<p>Concretely, this change would transform end-user code from this:</p>
<div class="codehilite"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">dst</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">safe_transmute</span>::<span class="o">&lt;</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">NeglectStability</span><span class="o">&gt;</span><span class="p">(</span><span class="n">src</span><span class="p">);</span><span class="w"></span>
</code></pre></div>


<p>...into this:</p>
<div class="codehilite"><pre><span></span><code><span class="c1">// Safe because I double-checked that `Dst` isn&#39;t using the pub-in-priv trick</span>
<span class="c1">// to mask library-imposed validity invariants</span>
<span class="kd">let</span><span class="w"> </span><span class="n">dst</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">unsafe_transmute</span>::<span class="o">&lt;</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">NeglectStability</span><span class="o">&gt;</span><span class="p">(</span><span class="n">src</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
</code></pre></div>


<p>...and that seems slightly ridiculous?</p>



<a name="205407603"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205407603" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205407603">(Jul 29 2020 at 20:11)</a>:</h4>
<p>We could add a lang item for "fully visible" which is only implemented for things that are fully exposed</p>



<a name="205407701"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205407701" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205407701">(Jul 29 2020 at 20:12)</a>:</h4>
<p>(I also seem to recall folks talking about making the pub-in-private stuff not allowed in future editions, but I'm not sure)</p>



<a name="205408093"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205408093" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205408093">(Jul 29 2020 at 20:15)</a>:</h4>
<p>Some priv-in-pub vectors are going to be eliminated, but that private module trick is here to stay.</p>
<p>I think the lang item suggestion is a good one. It doesn't actually need to be a language item per se, since the definition of "fully visible" that's relevant for transmutation is actually <em>already</em> a <em>little</em> more subtle than everything-is-public. I think I can tweak the RFC's wording a tiny bit to account for this without much issue!. :)</p>



<a name="205607301"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205607301" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205607301">(Jul 31 2020 at 15:50)</a>:</h4>
<blockquote>
<p>I think I can tweak the RFC's wording a tiny bit to account for this without much issue!. :)</p>
</blockquote>
<p>Silly me. This is actually pretty tricky.</p>



<a name="205607321"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205607321" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205607321">(Jul 31 2020 at 15:51)</a>:</h4>
<p>First: the "fully visible" approach. I think a reasonable definition of "fully visible" for a type is that:</p>
<p>- the type is marked marked <code>pub</code><br>
  - its fields are all marked <code>pub</code><br>
  - every module in its path is marked <code>pub</code><br>
  - the above requirements apply recursively to its fields.</p>
<p>This definition would preclude transmutations involving any types that aren't part of a crate's public API, which is a very harsh limitation.</p>



<a name="205607764"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205607764" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205607764">(Jul 31 2020 at 15:55)</a>:</h4>
<p>What if it was just that the fields had to be visible "to you" and also all the same visibility. Could that work?</p>
<p>Eg: within a crate you can see pub(crate) fields and can thus transmute that value only within the crate.</p>



<a name="205607882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205607882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205607882">(Jul 31 2020 at 15:56)</a>:</h4>
<p>Yeah, so the property that matters is <em>constructibility</em>. A type is constructible if its implicit constructor is in scope,  and its fields are constructible.</p>



<a name="205608113"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205608113" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205608113">(Jul 31 2020 at 15:58)</a>:</h4>
<p>But I'm struggling to weave constructability elegantly into trait resolution. Constructability depends on <em>where</em> you're trying to construct something. But where you write <code>Src: TransmuteInto&lt;Dst&gt;</code> might be very different from where you actually perform a transmutation (if you perform one at all).</p>



<a name="205609287"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205609287" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205609287">(Jul 31 2020 at 16:08)</a>:</h4>
<p>For instance, the proposed <code>IntoBytes</code> trait is defined for all <code>Src</code> and <code>Dst</code> such that <code>Src: TransmuteInto&lt;[u8; size_of::&lt;Src&gt;()]&gt;</code>. This blanket impl is defined in the standard library.</p>
<p>So an end-user using <code>IntoBytes</code> to transmute their type <code>Foo</code> won't actually be writing <code>TransmuteInto</code> at all. And, at the place where <code>TransmuteInto</code> does occur (i.e., the <code>where</code> clause of a blanket impl defined in the standard library), <code>Foo</code> is <em>definitely</em> not constructible.</p>



<a name="205609684"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205609684" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205609684">(Jul 31 2020 at 16:11)</a>:</h4>
<p>If <code>Foo</code> has generics, the rabbit hole only deepens.</p>



<a name="205610270"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205610270" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205610270">(Jul 31 2020 at 16:16)</a>:</h4>
<p>In the short term, I think the prudent thing to do is to simply demote <code>NeglectStability</code> to being an <em>unsafe</em> transmute option. I think this RFC exhausts its novelty budget justifying its stability declaration system; Introducing location-dependent trait resolution is too much to ask (and could be retrofitted onto safe transmute later on, anyways!).</p>
<p>Had we designed this RFC six years ago, I think I would have preferred making the pub-in-priv trick unsafe instead, but alas, here we are.</p>



<a name="205611026"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/RFC%3A%20Visibility/near/205611026" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/RFC.3A.20Visibility.html#205611026">(Jul 31 2020 at 16:23)</a>:</h4>
<p>I am <em>very</em> bummed, however, that this whole fiasco makes the distinction between safety and stability <em>really</em> subtle, and I'll probably need to revise the guide level explanation to reflect that subtlety.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>